package com.jason.fingerprint.service;

import android.app.AlertDialog;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.database.Cursor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.provider.MediaStore;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RemoteViews;
import android.widget.Toast;

import com.jason.fingerprint.R;
import com.jason.fingerprint.beans.ui.SoundBean;
import com.jason.fingerprint.common.RemainingTimeCalculator;
import com.jason.fingerprint.common.SoundRecorder;
import com.jason.fingerprint.common.SoundRecorder.OnStateChangedListener;
import com.jason.fingerprint.configs.DataConfig;
import com.jason.fingerprint.ui.SignInDetailActivity;

import java.io.File;
import java.lang.reflect.Field;

/**
 * @ClassName: SoundRecorderService
 * @Description: 录音服务类
 * @Author: John zhuqiangping@gmail.com
 * @Date: 2014年11月06日
 *
 */
public class SoundRecorderService extends Service implements
		OnStateChangedListener {
	private static final String TAG = "SoundRecorderService";
	private static final String ACTION_GOON_PLAY = "goon play";
	private static final String ACTION_GOON_RECORD = "goon record";
	private static final String ACTION_PAUSE = "pause";
	private static final String ACTION_STOP = "stop";
	private AudioManager mAudioManager = null;
	private SoundRecorderBinder mBinder = new SoundRecorderBinder();
	private int mCurrentState = 1;
	private AudioManager.OnAudioFocusChangeListener mFocusChangeListener = null;
	private boolean mGetFocus = false;
	private SoundRecorder mRecorder = null;
	private RemainingTimeCalculator mRemainingTimeCalculator = null;
	private boolean mRunForeground = false;
	private boolean mShowNotifiaction = true;
	private BroadcastReceiver mStorageBroastReceiver = null;
	private RemoteViews mNotificationView = null;
	private String mRequestedType;
	private boolean mDataExist = false;

	private boolean mDataInsertError = false;

	private Uri mSaveUri;
	boolean mSampleInterrupted = false;
	private TelephonyManager mTelephonyManager;
	private PhoneStateListener mPhoneStateListener;
	static int sOldCallState = TelephonyManager.CALL_STATE_IDLE;
	private int mAudioSourceType = MediaRecorder.AudioSource.MIC;
	private BroadcastReceiver mPowerOffReceiver = null;

//	private String mTitleName; // store title name of SignInDetailActivity
//	private String mRegisterType; // store register type of SignInDetailActivity
//	private SponsorInfo mSponsorInfo; // store sponsorInfo of
	// SignInDetailActivity

	private SoundBean mSoundBean;

	private String mRecordFileName;
	private StopRecordCallback mStopRecordCallback;

	private String mFileName;

	private MediaPlayer mPlayer;

	private boolean mIsPlaying;

	private String mPlayingFilePath;

	public void setFileName(String fileName){
		mFileName = fileName;
	}

	public String getFileName(){
		return mFileName;
	}

	private PhoneStateListener getPhoneStateListener() {
		PhoneStateListener phoneStateListener = new PhoneStateListener() {
			@Override
			public void onCallStateChanged(int state, String ignored) {
				switch (state) {
					case TelephonyManager.CALL_STATE_IDLE:
						if ((sOldCallState == TelephonyManager.CALL_STATE_OFFHOOK)
								&& !(mAudioSourceType == MediaRecorder.AudioSource.MIC)) {
							stopRecording();
						}
						break;

					case TelephonyManager.CALL_STATE_OFFHOOK:
						sOldCallState = TelephonyManager.CALL_STATE_OFFHOOK;
						break;

					default:
						// The control should not come here
						Log.e(TAG, "Unknown call state");
						break;
				}
			}
		};
		return phoneStateListener;
	}

	@Override
	public void onCreate() {
		Log.i(TAG, "<onCreate> start");
		super.onCreate();
		mDataExist = false;
		mAudioManager = ((AudioManager) getSystemService(Context.AUDIO_SERVICE));
		mRecorder = new SoundRecorder();
		mRecorder.setOnStateChangedListener(this);
		mRemainingTimeCalculator = new RemainingTimeCalculator(this);
		mFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
			public void onAudioFocusChange(int paramInt) {
				Log.i(TAG, "<onAudioFocusChange> audio focus changed to "
						+ paramInt);
				if (paramInt == AudioManager.AUDIOFOCUS_GAIN) {
					Log.i(TAG,
							"<onAudioFocusChange> audio focus changed to AUDIOFOCUS_GAIN");
					mGetFocus = true;
				} else if ((paramInt == AudioManager.AUDIOFOCUS_LOSS)
						|| (paramInt == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT)) {
					Log.i(TAG,
							"<onAudioFocusChange> audio focus loss, stop recording");
					mGetFocus = false;
					if (mRecorder == null) {
						return;
					}
					if ((mRecorder.getState() == SoundRecorder.STATE_RECORDING)
							|| (mRecorder.getState() == SoundRecorder.STATE_PAUSE_RECORDING)) {
						stopRecording();

						if (getRecordSampleLength() < 1) {
							Toast.makeText(
									SoundRecorderService.this
											.getApplicationContext(),
									R.string.record_file_duration_lessthan_one_second,
									Toast.LENGTH_SHORT).show();
							deleteRecord();
							return;
						}

						if (isCurrentFileWaitToSave()) {
							String fileName = mRecorder
									.sampleFile()
									.getName()
									.substring(
											0,
											mRecorder.sampleFile().getName()
													.lastIndexOf(".tmp"));
							saveRecord(fileName, "audio/" + mRecorder.getType());
						}
					} else if (mRecorder.getState() == SoundRecorder.STATE_PLAYING) {
						// stopPlay();
					}
				}
			}
		};
		mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		mPhoneStateListener = getPhoneStateListener();
		registerBroadcastReceivcer();
		IntentFilter localIntentFilter = new IntentFilter();
		localIntentFilter.addAction(ACTION_GOON_PLAY);
		localIntentFilter.addAction(ACTION_GOON_RECORD);
		localIntentFilter.addAction(ACTION_PAUSE);
		localIntentFilter.addAction(ACTION_STOP);
		Log.i(TAG, "<onCreate> end");
	}

	//播放录音
	public void playRecord(String path,MediaPlayer.OnCompletionListener listener){
		try {
			mPlayer = new MediaPlayer();//设置要播放的文件
			mPlayingFilePath = path;
			mPlayer.setDataSource(path);
			mPlayer.setOnCompletionListener(listener);
			mPlayer.prepareAsync();
			mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
				@Override
				public void onPrepared(MediaPlayer mp) {
					//播放
					mPlayer.start();
					mIsPlaying = true;
				}
			});
		}catch(Exception e){
			mIsPlaying = false;
			Log.e(TAG, "playRecord prepare() failed");
		}
	}

	//停止播放录音
	public void stopRecord(){
		try{
			if (mPlayer == null){
				mPlayer = new MediaPlayer();
			}
			mPlayer.stop();
			mPlayer.release();
			mIsPlaying = false;
			mPlayingFilePath = null;
		}catch (Exception e){
			mPlayer = null;
			mIsPlaying = false;
			mPlayingFilePath = null;
			e.printStackTrace();
		}
	}

	//当前播放器播放的录音
	public String getPlayFilePath(){
		return mPlayingFilePath;
	}

	//当前播放器的播放状态
	public boolean isPlaying(){
		return mIsPlaying;
	}


	public boolean saveRecord() {
		if (mRequestedType == null) {
			mRequestedType = DataConfig.AUDIO_WAVE;
		}
		return saveRecord(mRecordFileName, mRequestedType);
	}

	public boolean saveRecord(String name) {
		if (mRequestedType == null) {
			mRequestedType = DataConfig.AUDIO_WAVE;
		}
		return saveRecord(name, mRequestedType);
	}

	public boolean saveRecord(String name, String type) {
		mRequestedType = type;
		String lastName = name + mRecorder.getType();
		Log.d("XXX", "saveReocrd >> name: " + lastName);
		Uri uri = null;
		if (mRecorder.sampleLength() <= 0) {
			mRecorder.delete();
			return false;
		}
		try {
			if (isFileExist(mRecorder.getSampleDir().getAbsolutePath() + "/"
					+ lastName)) {
				return false;
			}
			renameRecordSampleFile(lastName);
			uri = addToMediaDB(new File(mRecorder.getSampleDir(), lastName));
		} catch (UnsupportedOperationException ex) {
			return false;
		} finally {
			if (uri == null && mDataExist) {
				mDataExist = false;
				return false;
			} else if (uri == null && mDataInsertError) {
				mDataInsertError = false;
				return false;
			} else {
				Toast.makeText(getApplicationContext(),
						R.string.tell_save_record_success, Toast.LENGTH_SHORT)
						.show();
			}
		}
		mRecorder.clear();
		mSaveUri = uri;
		return true;
	}

	private boolean isFileExist(String path) {
		Log.d(TAG, "isFileExist path : " + path);
		Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
		final String[] ids = new String[] { MediaStore.Audio.Playlists._ID };
		final String where = MediaStore.Audio.Playlists.DATA + "=?";
		final String[] args = new String[] { path };
		Cursor cursor = query(uri, ids, where, args, null);

		if (cursor != null && cursor.getCount() > 0) {
			mDataExist = true;
			cursor.close();
			Toast.makeText(getApplicationContext(),
					R.string.record_filename_same, Toast.LENGTH_SHORT).show();
			return true;
		}
		cursor.close();
		return false;
	}

	public Uri getSaveUri() {
		return mSaveUri;
	}

	public void setAudioSourceType(int type) {
		mAudioSourceType = type;
	}

	/*
	 * Make sure we're not recording music playing in the background, ask the
	 * MediaPlaybackService to pause playback.
	 */
	public void stopAudioPlayback() {
		// Shamelessly copied from MediaPlaybackService.java, which
		// should be public, but isn't.
		Intent i = new Intent("com.android.music.musicservicecommand");
		i.putExtra("command", ACTION_PAUSE);
		mAudioManager.requestAudioFocus(mFocusChangeListener,
				AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
		sendBroadcast(i);
		mGetFocus = true;
		try {
			Thread.sleep(300);
		} catch (InterruptedException ex) {
			Log.e(TAG, "sleep() for stop wait interrupted");
		}
	}

	public void abandonAudioFocus() {
		if ((mGetFocus) && (mAudioManager != null)
				&& (mFocusChangeListener != null)) {
			if (mAudioManager.abandonAudioFocus(mFocusChangeListener) != 1) {
				Log.e(TAG, "<abandonAudioFocus()> abandon audio focus faild");
				mGetFocus = true;
			} else {
				Log.i(TAG, "<abandonAudioFocus()> abandon audio focus success");
				mGetFocus = false;
			}
		}
	}

	/*
	 * Adds file and returns content uri.
	 */
	private Uri addToMediaDB(File file) {
		Resources res = getResources();
		ContentValues cv = new ContentValues();
		long current = System.currentTimeMillis();
		long modDate = file.lastModified();
		String title = getRecordStartTime();
		long sampleLengthMillis = getRecordSampleLength() * 1000L;
		// mLastFileName = file.getAbsolutePath().substring(
		// file.getAbsolutePath().lastIndexOf("/") + 1,
		// file.getAbsolutePath().length())
		// .replace("-", "");

		// Label the recorded audio file as MUSIC so that the file
		// will be displayed automatically
		cv.put(MediaStore.Audio.Media.IS_MUSIC, "1");
		cv.put(MediaStore.Audio.Media.TITLE, title);
		cv.put(MediaStore.Audio.Media.DATA, file.getAbsolutePath());
		cv.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000));
		cv.put(MediaStore.Audio.Media.DATE_MODIFIED, (int) (modDate / 1000));
		cv.put(MediaStore.Audio.Media.DURATION, sampleLengthMillis);
		cv.put(MediaStore.Audio.Media.MIME_TYPE, mRequestedType);

		cv.put(MediaStore.Audio.Media.ARTIST,
				res.getString(R.string.audio_db_artist_name));
		cv.put(MediaStore.Audio.Media.ALBUM,
				res.getString(R.string.audio_db_album_name));
		Log.d(TAG, "Inserting audio record: " + cv.toString());
		ContentResolver resolver = getContentResolver();
		Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
		Log.d(TAG, "ContentURI: " + base);
		Uri result;
		try {
			result = resolver.insert(base, cv);
		} catch (Exception exception) {
			result = null;
		}
		if (result == null) {
			if (isFileExist(file.getAbsolutePath())) {
				Log.d(TAG, "Insert error : file exist");
			} else {
				mDataInsertError = true;
				AlertDialog dialog = new AlertDialog.Builder(this)
						.setTitle(R.string.app_name)
						.setMessage(R.string.error_mediadb_new_record)
						.setPositiveButton(R.string.sure, null)
						.setCancelable(false).create();
				dialog.getWindow().setType(
						WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
				dialog.show();
			}
			return null;
		}
		if (getPlaylistId(res) == -1) {
			createPlaylist(res, resolver);
		}
		int audioId = Integer.valueOf(result.getLastPathSegment());
		addToPlaylist(resolver, audioId, getPlaylistId(res));

		// Notify those applications such as Music listening to the
		// scanner events that a recorded audio file just created.
		sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
		return result;
	}

	/*
	 * Add the given audioId to the playlist with the given playlistId; and
	 * maintain the play_order in the playlist.
	 */
	private void addToPlaylist(ContentResolver resolver, int audioId,
							   long playlistId) {
		String[] cols = new String[] { "count(*)" };
		Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external",
				playlistId);
		Cursor cur = resolver.query(uri, cols, null, null, null);
		cur.moveToFirst();
		final int base = cur.getInt(0);
		cur.close();
		ContentValues values = new ContentValues();
		values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER,
				Integer.valueOf(base + audioId));
		values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, audioId);
		resolver.insert(uri, values);
	}

	/*
	 * Create a playlist with the given default playlist name, if no such
	 * playlist exists.
	 */
	private Uri createPlaylist(Resources res, ContentResolver resolver) {
		ContentValues cv = new ContentValues();
		cv.put(MediaStore.Audio.Playlists.NAME, "My recordings");
		Uri uri = resolver.insert(
				MediaStore.Audio.Playlists.getContentUri("external"), cv);
		if (uri == null) {
			AlertDialog dialog = new AlertDialog.Builder(this)
					.setTitle(R.string.app_name)
					.setMessage(R.string.error_mediadb_new_record)
					.setPositiveButton(R.string.sure, null)
					.setCancelable(false).create();
			dialog.getWindow().setType(
					WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
			dialog.show();
		}
		return uri;
	}

	/*
	 * Obtain the id for the default play list from the audio_playlists table.
	 */
	private int getPlaylistId(Resources res) {
		Uri uri = MediaStore.Audio.Playlists.getContentUri("external");
		final String[] ids = new String[] { MediaStore.Audio.Playlists._ID };
		final String where = MediaStore.Audio.Playlists.NAME + "=?";
		final String[] args = new String[] { "My recordings" };
		Cursor cursor = query(uri, ids, where, args, null);
		if (cursor == null) {
			Log.v(TAG, "query returns null");
		}
		int id = -1;
		if (cursor != null) {
			cursor.moveToFirst();
			if (!cursor.isAfterLast()) {
				id = cursor.getInt(0);
			}
		}
		cursor.close();
		return id;
	}

	/*
	 * A simple utility to do a query into the databases.
	 */
	private Cursor query(Uri uri, String[] projection, String selection,
						 String[] selectionArgs, String sortOrder) {
		try {
			ContentResolver resolver = getContentResolver();
			if (resolver == null) {
				return null;
			}
			return resolver.query(uri, projection, selection, selectionArgs,
					sortOrder);
		} catch (UnsupportedOperationException ex) {
			return null;
		}
	}

	public boolean isCurrentFileWaitToSave() {
		if (mRecorder.sampleFile().getAbsolutePath() == null)
			return false;
		return mRecorder.sampleFile().getAbsolutePath().endsWith(".tmp");
	}

	public RemainingTimeCalculator getRemainingTimeCalculator() {
		return mRemainingTimeCalculator;
	}

	private void registerBroadcastReceivcer() {
		if (mStorageBroastReceiver == null) {
			mStorageBroastReceiver = new BroadcastReceiver() {
				public void onReceive(Context paramContext, Intent paramIntent) {
					String action = paramIntent.getAction();
					if ((action.equals(Intent.ACTION_MEDIA_EJECT) || action
							.equals(Intent.ACTION_MEDIA_UNMOUNTED))
							&& mRecorder.getState() != SoundRecorder.STATE_IDLE
							&& paramIntent.getDataString().contains(
							mRecorder.getSampleDir().getParent())) {
						stopRecording();
						deleteRecord();
					}
				}
			};
			IntentFilter localIntentFilter2 = new IntentFilter();
			localIntentFilter2.addAction("android.intent.action.MEDIA_EJECT");
			localIntentFilter2.addAction("android.intent.action.MEDIA_MOUNTED");
			localIntentFilter2
					.addAction("android.intent.action.MEDIA_UNMOUNTED");
			localIntentFilter2.addDataScheme("file");
			registerReceiver(mStorageBroastReceiver, localIntentFilter2);
			Log.i(TAG,
					"<registerExternalStorageListener> register mStorageBroastReceiver");
		}
		registerPowerOffListener();
	}

	/*
	 * Registers an intent to listen for ACTION_SHUTDOWN notifications.
	 */
	private void registerPowerOffListener() {
		if (mPowerOffReceiver == null) {
			mPowerOffReceiver = new BroadcastReceiver() {
				@Override
				public void onReceive(Context context, Intent intent) {
					String action = intent.getAction();
					if (action.equals(Intent.ACTION_SHUTDOWN)) {
						stopRecording();
						deleteRecord();
					}
				}
			};
			IntentFilter iFilter = new IntentFilter();
			iFilter.addAction(Intent.ACTION_SHUTDOWN);
			registerReceiver(mPowerOffReceiver, iFilter);
		}
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// While we're in the foreground, listen for phone state changes.
		mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		mTelephonyManager.listen(mPhoneStateListener,
				PhoneStateListener.LISTEN_CALL_STATE);

		Log.i(TAG, "<onStartCommand> start");
		if (intent == null) {
			return super.onStartCommand(intent, flags, startId);
		}
		String action = intent.getAction();
		Log.i(TAG, "<onStartCommand> action = " + action);
		if (action == null) {
			return super.onStartCommand(intent, flags, startId);
		}
		if ((action.equals(ACTION_GOON_RECORD))
				&& (mRecorder.getState() == SoundRecorder.STATE_PAUSE_RECORDING)) {
			Log.i(TAG, "<onStartCommand> ACTION_GOON_RECORD");
			resumeRecording();
		}
		/*
		 * else if ((str.equals(ACTION_GOON_PLAY)) && (mRecorder.state() ==
		 * Recorder.STATE_PAUSE_PLAYING)) { Log.i(TAG,
		 * "<onStartCommand> ACTION_GOON_PLAY"); playCurrentFile(); }
		 */else if (action.equals(ACTION_PAUSE)) {
			Log.i(TAG, "<onStartCommand> ACTION_PAUSE");
			if (mRecorder.getState() == SoundRecorder.STATE_RECORDING) {
				pauseRecording();
			}
			/*
			 * else if (mRecorder.state() == Recorder.STATE_PLAYING) {
			 * pausePlay(); }
			 */
		} else if (action.equals(ACTION_STOP)) {
			Log.i(TAG, "<onStartCommand> ACTION_STOP");
			if ((mRecorder.getState() == SoundRecorder.STATE_RECORDING)
					|| (mRecorder.getState() == SoundRecorder.STATE_PAUSE_RECORDING)) {
				stopRecording();
			}/*
			 * else if ((mRecorder.state() == Recorder.STATE_PLAYING) ||
			 * (mRecorder.state() == Recorder.STATE_PAUSE_PLAYING)) {
			 * stopPlay(); }
			 */
		}
		Log.i(TAG, "<onStartCommand> end");
		return super.onStartCommand(intent, flags, startId);
	}

	/**
	 * 设置音频格式开始录音
	 * @param type 音频格式，例如：DataConfig.AUDIO_AMR.
	 */
	public void record(String type) {
		mRequestedType = type;
		if (DataConfig.AUDIO_AMR.equals(mRequestedType)) {
			mRemainingTimeCalculator.setBitRate(DataConfig.BITRATE_AMR);
			setRecordChannels(1);
			setRecordSamplingRate(DataConfig.SAMPLERATE_8000);
			record(MediaRecorder.OutputFormat.RAW_AMR, ".amr",
					this, mAudioSourceType,
					MediaRecorder.AudioEncoder.AMR_NB);
		} else if (DataConfig.AUDIO_WAVE.equals(mRequestedType)) {
			mRemainingTimeCalculator.setBitRate(DataConfig.BITRATE_AMR);
			setRecordChannels(1);
			setRecordSamplingRate(DataConfig.SAMPLERATE_8000);
			record(MediaRecorder.OutputFormat.RAW_AMR, ".wav",
					this, mAudioSourceType,
					MediaRecorder.AudioEncoder.AMR_NB);
		} else if (DataConfig.AUDIO_3GPP.equals(mRequestedType)) {
			mRemainingTimeCalculator.setBitRate(DataConfig.BITRATE_3GPP);
			setRecordChannels(1);
			record(MediaRecorder.OutputFormat.THREE_GPP, ".3gpp",
					this, mAudioSourceType,
					MediaRecorder.AudioEncoder.AMR_NB);
		} else if (DataConfig.AUDIO_AAC_MP4.equals(mRequestedType)) {
			mRemainingTimeCalculator.setBitRate(DataConfig.BITRATE_3GPP);
			setRecordSamplingRate(DataConfig.SAMPLERATE_MULTI_CH);
			record(MediaRecorder.OutputFormat.THREE_GPP, ".3gpp",
					this, mAudioSourceType, MediaRecorder.AudioEncoder.AAC);
		} else {
			throw new IllegalArgumentException(
					"Invalid output file type requested");
		}

	}

	/**
	 * 设置音频格式开始录音
	 * @param type 音频格式，例如：DataConfig.AUDIO_AMR.
	 */
	public void record(String type,String modelName) {
		mRequestedType = type;
		if (DataConfig.AUDIO_AMR.equals(mRequestedType)) {
			mRemainingTimeCalculator.setBitRate(DataConfig.BITRATE_AMR);
			setRecordChannels(1);
			setRecordSamplingRate(DataConfig.SAMPLERATE_8000);
			record(MediaRecorder.OutputFormat.RAW_AMR, ".amr",
					this, mAudioSourceType,
					MediaRecorder.AudioEncoder.AMR_NB,modelName);
		} else if (DataConfig.AUDIO_WAVE.equals(mRequestedType)) {
			mRemainingTimeCalculator.setBitRate(DataConfig.BITRATE_AMR);
			setRecordChannels(1);
			setRecordSamplingRate(DataConfig.SAMPLERATE_8000);
			record(MediaRecorder.OutputFormat.RAW_AMR, ".wav",
					this, mAudioSourceType,
					MediaRecorder.AudioEncoder.AMR_NB,modelName);
		} else if (DataConfig.AUDIO_3GPP.equals(mRequestedType)) {
			mRemainingTimeCalculator.setBitRate(DataConfig.BITRATE_3GPP);
			setRecordChannels(1);
			record(MediaRecorder.OutputFormat.THREE_GPP, ".3gpp",
					this, mAudioSourceType,
					MediaRecorder.AudioEncoder.AMR_NB,modelName);
		} else if (DataConfig.AUDIO_AAC_MP4.equals(mRequestedType)) {
			mRemainingTimeCalculator.setBitRate(DataConfig.BITRATE_3GPP);
			setRecordSamplingRate(DataConfig.SAMPLERATE_MULTI_CH);
			record(MediaRecorder.OutputFormat.THREE_GPP, ".3gpp",
					this, mAudioSourceType, MediaRecorder.AudioEncoder.AAC,modelName);
		} else {
			throw new IllegalArgumentException(
					"Invalid output file type requested");
		}

	}

	public void record(int outputfileformat, String extension, Context context,
					   int audiosourcetype, int codectype) {
		mRecorder.startRecording(outputfileformat, extension, context,
				audiosourcetype, codectype);
	}

	public void record(int outputfileformat, String extension, Context context,
					   int audiosourcetype, int codectype,String modelName) {
		mRecorder.startRecording(outputfileformat, extension, context,
				audiosourcetype, codectype,modelName);
	}

	/**
	 * 获取录音完成后的文件名
	 * @return
	 */
	public String getRecordFileName() {
		return mRecordFileName;
	}

	/**
	 * 弹出保存录音对话框
	 */
	private void showSaveRecordDialog() {
		LayoutInflater inflater = LayoutInflater.from(this.getApplicationContext());
		View contentView = inflater.inflate(R.layout.recordsave_dialog, null);
		AlertDialog.Builder build = new AlertDialog.Builder(this);
		final EditText renameView = (EditText) contentView
				.findViewById(R.id.record_renme_et);

		String path = getRecordSampleFile().getName();
		String fileName = path.substring(
				1 + path.lastIndexOf(File.separator), path.length());
		if (fileName.endsWith(".tmp"))
			fileName = fileName.substring(0, fileName.lastIndexOf(".tmp"));
		mRecordFileName = fileName;
		renameView.setText(mRecordFileName);
		renameView.setSelection(mRecordFileName.length());
		build.setView(contentView);
		build.setTitle(R.string.record_rename);
		build.setCancelable(false);
		build.setPositiveButton(R.string.save_record,
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						try {
							Field f = dialog.getClass().getSuperclass()
									.getDeclaredField("mShowing");
							f.setAccessible(true);
							f.set(dialog, false);
						} catch (Exception e) {
							e.printStackTrace();
						}

						String newName = renameView.getText().toString();
						if (newName != null && !newName.equals(mRecordFileName)) {
							mRecordFileName = newName;
						}

						if (mStopRecordCallback != null) {
							mStopRecordCallback.onPositive();
						}
					}
				});
		build.setNegativeButton(android.R.string.cancel,
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						try {
							Field f = dialog.getClass().getSuperclass()
									.getDeclaredField("mShowing");
							f.setAccessible(true);
							f.set(dialog, true);
						} catch (Exception e) {
							e.printStackTrace();
						}

						deleteRecord();
						mRecordFileName = null;

						if (mStopRecordCallback != null) {
							mStopRecordCallback.onNegative();
						}
					}
				});

		AlertDialog renameDialog = build.create();
		renameDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
		renameDialog.show();
		/* set size & pos */
		WindowManager.LayoutParams lp = renameDialog.getWindow().getAttributes();
		WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
		Display display = wm.getDefaultDisplay();
		if (display.getHeight() > display.getWidth()) {
			//lp.height = (int) (display.getHeight() * 0.5);
			lp.width = (int) (display.getWidth() * 1.0);
		} else {
			//lp.height = (int) (display.getHeight() * 0.75);
			lp.width = (int) (display.getWidth() * 0.5);
		}
		renameDialog.getWindow().setAttributes(lp);

		final Button positiveButton = renameDialog
				.getButton(AlertDialog.BUTTON_POSITIVE);
		renameView.addTextChangedListener(new TextWatcher() {
			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
										  int after) {
				// TODO Auto-generated method stub
			}

			@Override
			public void onTextChanged(CharSequence s, int start, int before,
									  int count) {
				if (s.toString().length() <= 0
						|| s.toString().matches(".*[/\\\\:*?\"<>|].*")
						|| !s.toString().matches(
						"[a-zA-Z0-9_.\\-\\s\u4e00-\u9fa5]+")) {
					String inputText = "";
					try {
						inputText = s.subSequence(start, start + count)
								.toString();
					} catch (IndexOutOfBoundsException ex) {
					}
					if (inputText.length() > 0
							&& ((inputText.matches(".*[/\\\\:*?\"<>|].*")) || !s
							.toString()
							.matches(
									"[a-zA-Z0-9_.\\-\\s\u4e00-\u9fa5]+"))) {
						Toast.makeText(SoundRecorderService.this,
								R.string.invalid_char_prompt,
								Toast.LENGTH_SHORT).show();
					}
					if (positiveButton != null) {
						positiveButton.setEnabled(false);
					}
				} else {
					if (positiveButton != null) {
						positiveButton.setEnabled(true);
					}
				}
			}

			@Override
			public void afterTextChanged(Editable s) {
				// TODO Auto-generated method stub
			}
		});
	}

	public void renameRecordSampleFile(String newname) {
		mRecorder.renameSampleFile(newname);
	}

	public long getCurrentRecordProgress() {
		return mRecorder.progress();
	}

	public void resumeRecording() {
		mRecorder.resumeRecording();
	}

	public void pauseRecording() {
		// mRecorder.pauseRecording();
	}

	public void stopRecording() {
		abandonAudioFocus();
		mRecorder.stop();
//		showSaveRecordDialog();
	}

	public void setRecordChannels(int channels) {
		mRecorder.setChannels(channels);
	}

	public void setRecordSamplingRate(int samplerate) {
		mRecorder.setSamplingRate(samplerate);
	}

	public void setRecordStoragePath(String path) {
		mRecorder.setStoragePath(path);
	}

	public int getRecordState() {
		return mRecorder.getState();
	}

	public void deleteRecord() {
		mRecorder.delete();
	}

	public String getRecordStartTime() {
		return mRecorder.getStartRecordingTime();
	}

	public int getRecordSampleLength() {
		return mRecorder.sampleLength();
	}

	public File getRecordSampleFile() {
		return mRecorder.sampleFile();
	}

	public int getCurrentState() {
		return mCurrentState;
	}

	public SoundRecorder getRecorder() {
		return mRecorder;
	}

	public void onDestroy() {
		Log.i(TAG, "<onDestroy>");
		if (mPowerOffReceiver != null) {
			unregisterReceiver(mPowerOffReceiver);
			mPowerOffReceiver = null;
		}
		if (mStorageBroastReceiver != null) {
			unregisterReceiver(mStorageBroastReceiver);
			mStorageBroastReceiver = null;
		}
		mTelephonyManager.listen(mPhoneStateListener,
				PhoneStateListener.LISTEN_NONE);
		mRecorder.removeOnStateChangedListener(this);
		mRecorder = null;
		mPlayer = null;
		mIsPlaying = false;
		super.onDestroy();
	}

	@Override
	public IBinder onBind(Intent intent) {
		Log.i(TAG, "<onBind>");
		return mBinder;
	}

	private Class mNotificationClass;

	public void setNotificationClass(Class notificationClass) {
		mNotificationClass = notificationClass;
	}

	private void showNotification(Context context) {
		if (!mShowNotifiaction) {
			hideNotifiaction();
			Log.i(TAG, "<showNotification> mShowNotifiaction == false, return");
			return;
		}
		if (mRecorder.getState() == SoundRecorder.STATE_IDLE) {
			Log.i(TAG, "<showNotification> not show in STATE_IDLE, return");
			return;
		}
		if (mNotificationView == null) {
			Log.i(TAG, "<showNotificatoin> create mNotificationView");
			mNotificationView = new RemoteViews(getPackageName(),
					R.layout.notification);
		}
		mNotificationView.setTextViewText(R.id.notify_app_name, getResources()
				.getString(R.string.app_name));
		Intent goonRecordIntent = new Intent(ACTION_GOON_RECORD);
		goonRecordIntent.setClass(context, SoundRecorderService.class);
		PendingIntent goonRecordPendingIntent = PendingIntent.getService(
				context, 0, goonRecordIntent, 0);
		mNotificationView.setOnClickPendingIntent(R.id.btn_goon_record,
				goonRecordPendingIntent);
		Intent stopRecordIntent = new Intent(ACTION_STOP);
		stopRecordIntent.setClass(context, SoundRecorderService.class);
		PendingIntent stopRecordPendingIntent = PendingIntent.getService(
				context, 0, stopRecordIntent, 0);
		mNotificationView.setOnClickPendingIntent(R.id.btn_stop,
				stopRecordPendingIntent);
		Intent pauseRecordIntent = new Intent(ACTION_PAUSE);
		pauseRecordIntent.setClass(context, SoundRecorderService.class);
		PendingIntent pauseRecordPendingIntent = PendingIntent.getService(
				context, 0, pauseRecordIntent, 0);
		mNotificationView.setOnClickPendingIntent(R.id.btn_pause,
				pauseRecordPendingIntent);
		//TODO 这里需要进入走访详情页面
		Intent intent = new Intent(this,
				mNotificationClass != null ? mNotificationClass
						: SignInDetailActivity.class);
		PendingIntent startAppPendingIntent = PendingIntent.getActivity(
				context, 0, intent, 0);
		mNotificationView.setOnClickPendingIntent(R.id.notify_app_icon,
				startAppPendingIntent);
		Notification notification = new Notification();
		notification.contentView = mNotificationView;
		notification.flags = (Notification.FLAG_ONGOING_EVENT | notification.flags);
		notification.icon = R.drawable.ic_launcher;
		notification.contentIntent = startAppPendingIntent;
		setNotification();
		Log.i(TAG, "<showNotificatoin> startForeground");
		startForeground(1, notification);
		mRunForeground = true;
	}

	private void setNotification() {
		Log.i(TAG, "<setNotification>");
		String path = mRecorder.sampleFile().getName();
		String fileName = path.substring(1 + path.lastIndexOf(File.separator),
				path.length());
		if (fileName.endsWith(".tmp"))
			fileName = fileName.substring(0, fileName.lastIndexOf(".tmp"));
		mNotificationView.setTextViewText(R.id.file_name, fileName);
		switch (mRecorder.getState()) {
			case SoundRecorder.STATE_PAUSE_PLAYING:
				mNotificationView
						.setViewVisibility(R.id.btn_goon_record, View.GONE);
				mNotificationView.setViewVisibility(R.id.btn_pause, View.GONE);
				break;
			case SoundRecorder.STATE_PAUSE_RECORDING:
				mNotificationView.setViewVisibility(R.id.btn_goon_record,
						View.VISIBLE);
				mNotificationView.setViewVisibility(R.id.btn_pause, View.GONE);
				break;
			case SoundRecorder.STATE_RECORDING:
				mNotificationView
						.setViewVisibility(R.id.btn_goon_record, View.GONE);
				mNotificationView.setViewVisibility(R.id.btn_pause, View.GONE);
				break;
			case SoundRecorder.STATE_PLAYING:
				mNotificationView.setViewVisibility(R.id.btn_stop, View.VISIBLE);
				break;
			default:
				break;
		}
	}

	private void hideNotifiaction() {
		Log.i(TAG, "<hideNotifiaction>");
		stopForeground(true);
		mRunForeground = false;
	}

	public class SoundRecorderBinder extends Binder {
		public SoundRecorderBinder() {
		}

		public SoundRecorderService getService() {
			return SoundRecorderService.this;
		}
	}

	@Override
	public void onStateChanged(int state) {
		if (state == SoundRecorder.STATE_IDLE
				|| state == SoundRecorder.STATE_STOP_RECORDING) {
			hideNotifiaction();
			abandonAudioFocus();
			return;
		}
//		showNotification(this);
	}

	@Override
	public void onError(int error) {

	}

//	public String getTitleName() {
//		return mTitleName;
//	}
//
//	public void setTitleName(String titleName) {
//		this.mTitleName = titleName;
//	}
//
//	public String getRegisterType() {
//		return mRegisterType;
//	}
//
//	public void setRegisterType(String registerType) {
//		this.mRegisterType = registerType;
//	}
//
//	public SponsorInfo getSponsorInfo() {
//		return mSponsorInfo;
//	}
//
//	public void setSponsorInfo(SponsorInfo sponsorInfo) {
//		this.mSponsorInfo = sponsorInfo;
//	}

	public void setStopRecordCallback(StopRecordCallback callback) {
		mStopRecordCallback = callback;
	}

	public SoundBean getSoundBean() {
		return mSoundBean;
	}

	public void setSoundBean(SoundBean mSoundBean) {
		this.mSoundBean = mSoundBean;
	}

	public interface StopRecordCallback {

		void onPositive();

		void onNegative();
	}
}
